/**
 * Created by JasonChou on 16/5/23.
 */


var bridge = {};
window.bridge = bridge;
!function (bridge) {
  window.isWsdk = navigator.userAgent.match(/wsdk/g) != null;
  bridge.isWsdk = window.isWsdk;
  if (!bridge.isWsdk)
    browser.init();

  bridge.isWechat = navigator.userAgent.match(/MicroMessenger/g) != null;

  bridge.isAndroid = navigator.userAgent.match(/Android/gi) != null;

  if (!bridge.isAndroid)
    bridge.isIOS = navigator.userAgent.match(/ios/gi) != null;
  else
    bridge.isIOS = false;

  bridge.cbMap = {};

  //native hooks
  var nativeHooks = ['resume', 'pause', 'scroll', 'refresh'];

  nativeHooks.forEach(function (nHookName) {

    var nhook = 'on' + replaceFirstUper(nHookName);

    var jsHooksName = nHookName + 'Hooks';
    bridge[jsHooksName] = [];

    bridge[nhook] = function () {
      var args = arguments;
      this[jsHooksName].forEach(function (hook) {
        var command = 'hook(';
        for (var i in args) {
          var arg = args[i];
          if (i > 0)
            command += ',';
          command += arg;
        }
        command += ')';
        eval(command);
      })
    };
  });

  bridge.callback = function (cbMethodName) {
    var cb = this.cbMap[cbMethodName];

    if (cb) {
      var args = [];

      if (arguments.length > 1) {
        var i = 1;
        for (; i < arguments.length; i++) {
          args.push(arguments[i]);
        }
      }

      cb.apply(window, args);

      delete this.cbMap[cbMethodName];
    }
  };

  var Client = function (name, methods) {
    var self = this;
    this.name = name;
    this.protocol = 'wsdk';
    this.separator = '&';

    methods.forEach(function (val) {

      var method = val;
      var ivMethod = val;

      if (val instanceof Object) {
        method = val.name;
        ivMethod = val._name;
      }

      self[method] = function () {
        this.invoke(ivMethod, arguments);
      };
    });

    nativeHooks.forEach(function (nHookName) {
      var hookSetMethodName = 'setOn' + replaceFirstUper(nHookName);
      var jsHooksName = nHookName + 'Hooks';

      self[hookSetMethodName] = function (cb) {
        bridge[jsHooksName].push(cb);
      }
    });
  };

  bridge.Client = Client;

  if (bridge.isWsdk)
    Client.prototype.invoke = function (method, args) {
      var request = this.assembleRequest(method, args);
      log(request);

      this.exec(request);
    };
  else {
    Client.prototype.invoke = function (method, args) {
      log(method, args);


      if (!browser[method])
        console.log(method + '浏览器未实现');
      else
        browser[method].apply(browser, args);
    };
  }

  Client.prototype.exec = function (url) {
    location.href = url;

    //var imgDom = document.createElement('img');
    //imgDom.setAttribute('src', url);
    //imgDom.setAttribute('type', 'hidden');
    //
    //document.getElementsByTagName('head')[0].appendChild(imgDom)
  };

  Client.prototype.assembleRequest = function (method, args) {
    var request = this.protocol + '://' + method;


    if (args && args.length > 0) {
      var params = '';

      var cb = args[args.length - 1];

      var hasCb = cb instanceof Function;

      if (hasCb) {

        var cbMethodName = this.name + '_' + Date.now();

        bridge.cbMap[cbMethodName] = cb;

        params += 'cb=' + cbMethodName;

        delete  args[args.length - 1];
      }

      //log(args);

      if (args.length > 0) {
        var _args = [];
        for (var key in args) {
          _args.push(args[key]);
        }

        _args = JSON.stringify(_args);
        _args = encodeURIComponent(_args);

        if (params)
          params += this.separator;
        params += 'args=' + _args;
      }

      request += '?' + params;
    }

    return request;
  };

  function replaceFirstUper(str) {
    str = str.toLowerCase();
    return str.replace(/\b(\w)|\s(\w)/g, function (m) {
      return m.toUpperCase();
    });
  }
}(bridge);

window.wsdk = new bridge.Client('wsdk', [
  'plus', 'hello', 'setName', 'go', 'close', 'refreshFinish', 'changeRefresh', 'toast','getUnreadMessageCount', 'share',{
    name: 'set',
    _name: 'ls_set'
  }, {
    name: 'get',
    _name: 'ls_get'
  }, {
    name: 'pop',
    _name: 'ls_pop'
  }
]);

wsdk.go = function (page) {
  if (Object.prototype.toString.call(page) === "[object String]") {
    page = {
      url: page,
      type: pageType.H5
    }
  }

  this.invoke('go', [page.url, page.type, page.params]);
};
